package bg.openid;

// bg.openid.ServletOpenid
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.xml.DOMConfigurator;
import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.MessageExtension;
import org.openid4java.message.MessageExtensionFactory;
import org.openid4java.message.ax.FetchRequest;
import org.springframework.util.Log4jConfigurer;

public class ServletOpenid extends HttpServlet {

	public static ConsumerManager manager;
	private ServletContext context;

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		context = config.getServletContext();
		System.out.println("ConsumerServlet context: " + context);
		try {
			this.manager = new ConsumerManager();
			System.out.println("Log4j initialized with bg_log4j.xml    start  <<<<<<<<<<<<<<<<<<<<<<<");

			DOMConfigurator.configureAndWatch("bg_log4j.xml");
			System.out.println("Log4j initialized with bg_log4j.xml  done   <<<<<<<<<<<<<<<<<<<<<<<");

		} catch (Exception e) {
			e.printStackTrace();
			// throw new ServletException(e);
		}
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Bean bean = new Bean();
		request.getSession().setAttribute("bean", bean);
		String action = request.getParameter("action");
		try {
			if (action == null) {
				bean.addComment("action is null");
			} else if (action.equalsIgnoreCase("login")) {
				this.authRequestBG(request, response, bean);
			} else if (action.equalsIgnoreCase("init")) {
				bean.setComment("action = init");
				forward_default(request, response);
			} else if (action.equalsIgnoreCase("clean")) {
				bean.setComment("action = clean");
				forward_default(request, response);
			}
		} catch (Exception e) {
			bean.addException(e);
			e.printStackTrace();
			forward_default(request, response);
		}
	}

	private void forward_default(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/bg2.jsp");
		dispatcher.forward(request, response);
	}

	@SuppressWarnings("unchecked")
	private void authRequestBG(HttpServletRequest request, HttpServletResponse response, Bean bean) throws Exception {
		String identifierStr = request.getParameter("identifier");
		identifierStr = identifierStr.trim();
		System.out.println("ServletOpenId :::   identifierStr :" + identifierStr);
		bean.setIdentifier(identifierStr);
		// perform discovery on the user-supplied identifier
		List<DiscoveryInformation> discoveries = manager.discover(identifierStr);
		// attempt to associate with the OpenID provider
		// and retrieve one service endpoint for authentication
		bean.display(discoveries);
		DiscoveryInformation discovered = manager.associate(discoveries);
		bean.addComment("discovered", discovered);
		// store the discovery information in the user's session for later use
		// leave out for stateless operation / if there is no session
		HttpSession session = request.getSession();
		session.setAttribute("discovered", discovered);
		// obtain a AuthRequest message to be sent to the OpenID provider
		String returnToUrl;
		// returnToUrl = request.getRequestURL().toString();
		returnToUrl = getUrlReturn(request);
		AuthRequest authReq = manager.authenticate(discovered, returnToUrl);

		String destinationURL = authReq.getDestinationUrl(true) + getSreg();
		bean.addComment("destinationURL : " + destinationURL);
		bean.displayUrl(destinationURL);
		response.sendRedirect(destinationURL);
	}

	private String getSreg() {
		String r = "";
		r += getEncoded("openid.ns.sreg", "http://openid.net/extensions/sreg/1.1");
		r += getEncoded("openid.sreg.required", "fullname,email");
		r += getEncoded("openid.sreg.optional", "gender,nickname");
		return r;
	}

	private String getEncoded(String k, String v) {
		return "&" + k.trim() + "=" + URLEncoder.encode(v);
	}

	private String getUrlReturn(HttpServletRequest request) {
		String r = request.getRequestURL().toString();
		r += "Return";
		return r;
	}

	private Bean getBean(HttpServletRequest request) {
		HttpSession session = request.getSession(true);
		Bean b = (Bean) session.getAttribute("bean");
		if (b == null) {
			b = new Bean();
		}
		return b;
	}

}
